#ifndef _core_dispatch_type_lookup_switch_hpp_
#define _core_dispatch_type_lookup_switch_hpp_

/** \file switch.hpp
 *  \author Adrian Schweizer
 *  \created  $Sa 18 Aug 03:48:01 pm CEST 2007 schwadri@SchwadriComp.local$
 *  \modified $So 19 Aug 03:48:56 pm CEST 2007 schwadri@SchwadriComp.local$
 */

#include <boost/mpl/assert.hpp>

#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/sequence_tag.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/size.hpp>

#include "../exception.hpp"

#include "detail/switch_map_impl.hpp"
#include "detail/switch_vector_impl.hpp"
#include "detail/default.hpp"

namespace core {

    namespace dispatch {

        namespace type_lookup {

            /** \brief key value to type mapper using a big switch statement
             *
             *  the supplied type list (Cases template param) may be a boost::mpl::vector or
             *  a boost::mpl::map
             */
            template<class Cases>
                struct switch_
                {
                    template<class Key, class Invoker>
                        typename Invoker::return_type type_lookup(Key key, Invoker& invoker)
                        {
                            //first check that Cases is in fact a sequence
                            BOOST_MPL_ASSERT((boost::mpl::is_sequence<Cases>));
                            typedef typename boost::mpl::sequence_tag<Cases>::type          sequence_tag;
                            typedef typename detail::get_switch_impl<sequence_tag>::type    impl_type;
                            typedef typename Invoker::return_type                           return_type;


                            typedef typename impl_type::template apply<boost::mpl::size<Cases>::value,
                                                                        Cases,
                                                                        return_type
                                                                        >::type         switcher;
                            return switcher::template eval<Key,Invoker,detail::throw_unhandled_key<return_type,Key> >(key,invoker,detail::throw_unhandled_key<return_type,Key>(),Cases());
                        }
                };

        } // namespace type_lookup
    } // namespace dispatch
} // namespace core

#endif // _core_dispatch_type_lookup_switch_hpp_
